from sqlalchemy import Column, Integer, String, ForeignKey, orm
from sqlalchemy.orm import relationship, backref

from app.libs.case_group_util.group_by_group import group_by_v
from app.libs.job import execute_debug_job
from app.libs.run_py import run_py
from app.libs.save_log import compute_time
from app.libs.sub_var import replace_var_dict
from app.models.base import db
from app.models.base import Base
from app.models.space import SpaceModel
import bson


class CaseGroupModel(Base):
    """
    用例组
    """
    __tablename__ = 'case_group'
    id = Column(Integer, primary_key=True)
    name = Column(String(80), nullable=False, comment='用例组名称')
    _execute_status = Column('execute_status', String(80), comment='执行状态')
    trigger = Column(String(80), comment='执行时机', default='interval')
    execute_time = Column(Integer, comment='循环时间')
    last_time = Column(String(30), comment='最后执行的时间')
    last_status = Column(String(30), comment='最后执行的状态')
    create_user = Column(Integer, ForeignKey('user.id'))
    update_user = Column(String(180))
    space_id = Column(Integer, ForeignKey('space.id'))
    space = relationship('SpaceModel', backref=backref('case_groups'))

    @orm.reconstructor
    def __init__(self):
        super(CaseGroupModel, self).__init__()
        self.fileds = ['id', 'name', 'execute_status', 'create_user', 'update_user', 'space_id', 'last_status',
                       'last_time', 'trigger', 'execute_time', 'create_time']

    def keys(self):
        return self.fileds

    def set_keys(self, keys):
        self.fileds = keys

    @property
    def execute_status(self):
        if int(self._execute_status) == 1:
            return True
        return False

    @execute_status.setter
    def execute_status(self, status):
        self._execute_status = status

    def get_page_group(self, cid):
        g_list = self.query.order_by(getattr(CaseGroupModel, 'create_time').desc()).filter(
            CaseGroupModel.status == 1).filter(CaseGroupModel.space_id == cid).all()
        gg_list = []

        for g in g_list:
            g.len = list(filter(lambda c: c.status != 0, g.cases)).__len__()
            g.last_time = compute_time(g.last_time)
            g.add_keys('len')
            gg_list.append(g)

        return gg_list

    @staticmethod
    def add_group(name, create_user, space_id, execute_status=False, execute_time=10):
        with db.auto_commit():
            group = CaseGroupModel()
            group.name = name
            group.create_user = create_user
            group.space_id = space_id
            group.execute_status = execute_status
            group.execute_time = execute_time
            db.session.add(group)

    @staticmethod
    def debug_case_group(cases):
        # 生成一个objid
        _id = str(bson.ObjectId())
        execute_debug_job(cases, _id)
        return _id

    @staticmethod
    def before_request(case, var_dict):
        # 替换数据
        if case['body']:
            # case['body'] = eval(case['body'].replace('\r', '').replace('\n', '').replace(' ', ''))
            case['body'] = (case['body'].replace('\r', '').replace('\n', '').replace(' ', ''))
        data = replace_var_dict(case, var_dict)
        return data

    @staticmethod
    def after_request(response, condition, var_dick):
        # 保存变量 执行结果
        result_str = run_py(response, condition, var_dick)
        if "错误类型" in result_str:
            return result_str

        return dict(var_dick, **result_str)

    @staticmethod
    def delete_case(s_id):
        s = CaseGroupModel().query.filter_by(id=s_id).first_or_404()
        with db.auto_commit():
            for c in s.cases:
                c.delete()
            s.delete()
            db.session.commit()

    def update_execute_status(self, s_id, status):
        s = self.query.filter_by(id=s_id).first_or_404()
        with db.auto_commit():
            s.execute_status = status
            db.session.commit()

    def update_status(self, s_id, last_time, error=None):
        s = self.query.filter_by(id=s_id).first_or_404()
        with db.auto_commit():
            s.last_time = last_time
            s.last_status = error
            db.session.commit()

    @staticmethod
    def put_group(g_id, name, trigger, execute_time=None):
        s = CaseGroupModel().query.filter_by(id=g_id).first_or_404()
        with db.auto_commit():
            s.name = name
            if execute_time:
                # TODO 查看定时任务是都开启，如果开启则修改任务的循环时间
                s.execute_time = int(execute_time)
            s.trigger = trigger
            db.session.commit()

    @staticmethod
    def get_ex_group():
        s_list = db.session.query(CaseGroupModel).filter(
            CaseGroupModel._execute_status == 1).filter(CaseGroupModel.status == 1).all()
        return group_by_v(s_list)
